package fx.mine.active.component.music;

import animatefx.animation.FadeOut;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import io.github.palexdev.materialfx.controls.MFXButton;
import io.github.palexdev.materialfx.controls.MFXSlider;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Text;
import javafx.util.Duration;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;

@Log4j2
public class PlayerContainer extends AnchorPane {
    private boolean played = false;
    private final String playUrl = getClass().getResource("/icon/play.png").toExternalForm();
    private final String temUrl = getClass().getResource("/icon/tem.png").toExternalForm();
    private MediaPlayer mediaPlayer = new MediaPlayer(new Media("https://m10.music.126.net/20220827202528/9288e70a6d3b1b5dc615c4399c450e29/yyaac/obj/wonDkMOGw6XDiTHCmMOi/3127361311/9af7/b601/79a8/f16ce67eeebc360d29a933a502a259eb.m4a"));
    private Node playItem;
    private Node lyric;
    private boolean previewClicked = false;
    private final SimpleStringProperty mp3Watcher = new SimpleStringProperty();
    private final SimpleBooleanProperty playingWatcher = new SimpleBooleanProperty();
    private ImageView play;
    private final Image temImage = new Image(temUrl);
    private final Image playImage = new Image(playUrl);

    @Getter
    private final SimpleStringProperty dynPreviewIconUrl = new SimpleStringProperty();
    private final Image image = new Image("https://p3.music.126.net/UvaJwHUEP_VDohZ6pBebiw==/109951165644287718.jpg?param=34y34");
    private final ImageView music = new ImageView(image);

    private final SimpleStringProperty sliderProgressTimeString = new SimpleStringProperty("00:00");
    private final SimpleDoubleProperty currentProgressIndicator = new SimpleDoubleProperty(1) {
        {
            addListener(new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                    mfxSlider.setValue(newValue.intValue());
                }
            });
        }
    };

    @Getter
    private final SimpleStringProperty playerNameWatcher = new SimpleStringProperty("");

    @Getter
    private final SimpleStringProperty songNameWatcher = new SimpleStringProperty("");
    private int total;

    private final MFXSlider mfxSlider = new MFXSlider(0) {
        {
            prefWidth(720);
            minWidth(720);
            setMin(0);
            AnchorPane.setLeftAnchor(this, 205.0);
            AnchorPane.setBottomAnchor(this, 15.0);
            AnchorPane.setRightAnchor(this, 20.0);
        }
    };

    public PlayerContainer() {
        dynPreviewIconUrl.addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                if (StrUtil.isNotBlank(newValue)) {
                    music.setImage(new Image(newValue));
                }
            }
        });
        setPrefHeight(40);

        customLayout();

        addPlayControl();

        addPrevControl();

        addNextControl();

        addPreviewControl();

        addShowControl();

        getStyleClass().add("playerContainer");
        getStylesheets().add(getClass().getResource("/css/playerContainer.css").toExternalForm());

        mp3Watcher.addListener((observable, oldValue, newValue) -> {
            mediaPlayer = createPlayer(newValue);
            playingWatcher.set(true);
            mediaPlayer.play();
        });
        playingWatcher.addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                log.info("playing watcher old = {} , new = {}", oldValue, newValue);
                if (newValue) {
                    play.setImage(temImage);
                } else {
                    play.setImage(playImage);
                }
            }
        });
    }

    public MediaPlayer createPlayer(String mediaUrl) {
        mediaPlayer.stop();
        mediaPlayer.dispose();
        mediaPlayer = new MediaPlayer(new Media(mediaUrl));
        mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() {
            @Override
            public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
                try {
                    sliderProgressTimeString.set(timeShowFormat((int) newValue.toMillis()));
                    currentProgressIndicator.set((int) newValue.toSeconds());
                } catch (Exception e) {
                    log.error(e);
                }
            }
        });
        mediaPlayer.setOnEndOfMedia(() -> {
            playingWatcher.set(false);
        });
        return mediaPlayer;
    }

    private void addShowControl() {
        var hbox = new HBox();
        AnchorPane.setTopAnchor(hbox, 5.0);
        AnchorPane.setLeftAnchor(hbox, 200.0);
        AnchorPane.setRightAnchor(hbox, 10.0);
        hbox.setAlignment(Pos.CENTER_LEFT);
        hbox.setSpacing(20);

        var musicName = new Text(songNameWatcher.get());
        musicName.textProperty().bind(songNameWatcher);
        hbox.getChildren().add(musicName);

        var playerName = new Text(playerNameWatcher.get());
        playerName.textProperty().bind(playerNameWatcher);
        hbox.getChildren().add(playerName);

        var timeShow = new Text(sliderProgressTimeString.get());
        timeShow.textProperty().bind(sliderProgressTimeString);
        hbox.getChildren().add(timeShow);

        getChildren().add(hbox);
        getChildren().add(mfxSlider);
    }

    private void addPreviewControl() {
        music.setFitWidth(35);
        music.setFitHeight(35);
        MFXButton musicButton = new MFXButton("", music);
        AnchorPane.setTopAnchor(musicButton, 2.0);
        AnchorPane.setBottomAnchor(musicButton, 2.0);
        AnchorPane.setLeftAnchor(musicButton, 140.0);

        musicButton.setOnMouseClicked(event -> {
            this.playItem = ((MusicPane) getParent()).getPlayItems();
            this.lyric = ((MusicPane) getParent()).getLyricsContainer();

            Node currentShowNode = previewClicked ? lyric : playItem;
            FadeOut fadeOut = new FadeOut();
            fadeOut.setResetOnFinished(true);
            fadeOut.setNode(currentShowNode);
            fadeOut.setOnFinished(e -> {
                currentShowNode.toFront();
                PlayerContainer.this.toFront();
            });
            fadeOut.setSpeed(0.5);
            fadeOut.play();
            previewClicked = !previewClicked;
        });

        musicButton.getStyleClass().add("play");
        getChildren().add(musicButton);
    }

    public void trigger(String songJsonStr) {
        JSONObject jsonObject = JSON.parseObject(songJsonStr);
        String mp3Url = (String) JSONPath.eval(jsonObject, "$.data[0].url");
        this.total = (Integer) JSONPath.eval(jsonObject, "$.data[0].time");
        mfxSlider.setMax(total / 1000);
        mp3Watcher.set(mp3Url);
    }

    private void addNextControl() {
        ImageView next = new ImageView(getClass().getResource("/icon/next.png").toExternalForm());
        next.setFitHeight(28);
        next.setFitWidth(28);
        MFXButton nextButton = new MFXButton("", next);
        nextButton.getStyleClass().add("play");
        nextButton.setOnMouseClicked(event -> {
            mediaPlayer = createPlayer("https://m10.music.126.net/20220827204554/b966e7d89b9dcd4448f88abc3777fb47/yyaac/obj/wonDkMOGw6XDiTHCmMOi/3035987194/6fbe/761c/7a69/770ff831345dd3d65f4a5b554d607922.m4a");
            mediaPlayer.play();
        });
        AnchorPane.setTopAnchor(nextButton, 6.0);
        AnchorPane.setLeftAnchor(nextButton, 90.0);
        AnchorPane.setBottomAnchor(nextButton, 6.0);
        getChildren().add(nextButton);
    }

    private void addPrevControl() {
        ImageView prev = new ImageView(getClass().getResource("/icon/previous.png").toExternalForm());
        prev.setFitWidth(28);
        prev.setFitHeight(28);
        MFXButton prevButton = new MFXButton("", prev);
        prevButton.getStyleClass().add("play");
        prevButton.setOnMouseClicked(event -> {
            mediaPlayer = createPlayer("https://m10.music.126.net/20220828000641/f575fe22ad012aa6de14e8de12d3757d/yyaac/obj/wonDkMOGw6XDiTHCmMOi/3127361311/9af7/b601/79a8/f16ce67eeebc360d29a933a502a259eb.m4a");
            mediaPlayer.play();
        });
        AnchorPane.setTopAnchor(prevButton, 6.0);
        AnchorPane.setLeftAnchor(prevButton, 10.0);
        AnchorPane.setBottomAnchor(prevButton, 6.0);
        getChildren().add(prevButton);
    }

    private void addPlayControl() {
        this.play = new ImageView(playImage);
        play.setFitWidth(35);
        play.setFitHeight(35);
        MFXButton playButton = new MFXButton("", play);
        playButton.setOnMouseClicked(event -> {
            if (played) {
                play.setImage(playImage);
                mediaPlayer.pause();
            } else {
                play.setImage(temImage);
                mediaPlayer.play();
            }
            played = !played;
        });
        AnchorPane.setTopAnchor(playButton, 2.0);
        AnchorPane.setLeftAnchor(playButton, 46.0);
        AnchorPane.setBottomAnchor(playButton, 2.0);
        playButton.getStyleClass().add("play");
        getChildren().add(playButton);
    }

    private void customLayout() {
        AnchorPane.setBottomAnchor(this, 0.0);
        AnchorPane.setLeftAnchor(this, 50.0);
        AnchorPane.setRightAnchor(this, 50.0);
    }

    public static String timeShowFormat(int time) {
        int sec = time / 1000;
        int minute = sec / 60;
        int secs = sec % 60;
        return minute + ":" + secs;
    }

}
